/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Model;

import AirLine.Airport;
import Database.Airports;
import edu.chl.chalmers.fatclient.sb.Flight;
import java.util.*;
import java.sql.Timestamp;


import java.sql.SQLException;

/**
 *
 * @author oskar
 */
public class TripHandler {

    public static final int SORT_BY_PRICE = 0,  SORT_BY_TIME = 1;
    private int passengers;
    private int numberOfTrips = 5;
    private Airport departureAirport;
    private Airport destinationAirport;
    private String currentAirport;
    private Timestamp earliestDepartureTime,  latestDepartureTime;
    //private ArrayList<Flight> flights;
    private TreeSet<Flight> flightList;

    //private ArrayList<Airport> airports;
    private TreeSet<Airport> airports;
    private String[] airlines;
    private int sortingOrder;
    private PriorityQueue<Trip> pq;
    private HashSet<String> visited;
    private HashMap<String, ArrayList<Flight>> neighbourMap;
    private TreeSet<Trip> tripList;
    private ArrayList<String> airlineList;


    
     public TripHandler(Airport from, Airport to, int passengers, int sortingOrder, Timestamp earliestDepartureTime, Airports airports, TreeSet<Flight> flights, ArrayList<String> airlineList) {
        setAirports(airports);
        this.flightList = flights;

        setParameters(from, to, passengers, sortingOrder, earliestDepartureTime, airlineList);
        
    }

    
    
    //Needed to set before running getTrips()
    public void setParameters(Airport from, Airport to, int passengers, int sortingOrder, Timestamp earliestDepartureTime, ArrayList<String> airlineList) {
        //this.airlineList=airlineList;
        this.airlineList=airlineList;
        departureAirport = from;
        destinationAirport = to;
        this.sortingOrder = sortingOrder;
        this.passengers = passengers;
        this.earliestDepartureTime = earliestDepartureTime;

        //Max 24Hour forward
        //latestDepartureTime = new Timestamp(earliestDepartureTime.getTime() + 24 * 60 * 60 * 1000);
        //System.out.println("hääär"+earliestDepartureTime);
    }


    //Needed to set before running getTrips()
    public void setAirports(TreeSet<Airport> airports) {
        //this.airports = airports;
    }
    
    public void setAirports(Airports airports){
        
        try{
        this.airports=airports.getAirportsList();
        }
        catch(SQLException e)
        {
            System.out.println(e.getLocalizedMessage());
        }
        //airs=airports;
    }

    //Set the 3 seters above before running
    public TreeSet<Trip> getTrips() throws SQLException {
        
        
        if (sortingOrder == SORT_BY_PRICE) {
            tripList = new TreeSet<Trip>(new CostComparator());
        } else {
            tripList = new TreeSet<Trip>(new TimeComparator());
        }

        
        TreeSet<Flight> fl = new TreeSet<Flight>(flightList);
        createGraph(fl);
        createTrips();

        if (!tripList.isEmpty()) {
            for (Flight f : tripList.first().getFlights()) {
                //System.out.println("woot");
                
  

                fl.remove(f);
               
                createGraph(fl);
                createTrips();
                /*
                System.out.println("flightsize: "+flightList.size());
                System.out.println("bah, true? "+flightList.add(f));
                System.out.println(tripList.size());
                System.out.println(tripList);
                 * */
            }
        }
        return tripList;
    }

    private void createGraph(TreeSet<Flight> flightlist) {
        neighbourMap = new HashMap<String, ArrayList<Flight>>();
        for (Airport a : airports) {
            
            neighbourMap.put(a.getAirportCode(), new ArrayList<Flight>());
        }

        for (Flight f : flightlist) {
            if (f.getNumberOfFreeSeats() >= passengers && airlineList.contains(f.getAirline().getCode()))
            {
                
                  //  System.out.println("1111"+f.getAirline().getCode());
                //System.out.println("2222"+f.getAirline().getDbIdentifier());
                neighbourMap.get(f.getDepartureAirport().getAirportCode()).add(f);
                //System.out.println("departure: "+f.getDepartureAirport());
               // System.out.println("dest: "+f.getDestinationAirport());
            }

        }
    }

    private void createTrips() {
        Trip tempTrip = null;
        visited = new HashSet<String>();

        if (sortingOrder == SORT_BY_PRICE) {
            pq = new PriorityQueue<Trip>(50, new CostComparator());
        } else {
            pq = new PriorityQueue<Trip>(50, new TimeComparator());
        }

        for (Flight f : neighbourMap.get(departureAirport.getAirportCode())) {
            if (f.getDepartureTime().getTime() >= earliestDepartureTime.getTime()) {
                LinkedList<Flight> tempList = new LinkedList<Flight>();
                tempList.add(f);
                pq.add(new Trip(tempList));
            }
        }

        //System.out.println("pq siize: "+pq.size());

        visited.add(departureAirport.getAirportCode());
        //distanceMap.put(departureAirport, 0);
        currentAirport = departureAirport.getAirportCode();

        while (!visited.contains(destinationAirport.getAirportCode()) && !pq.isEmpty()) {
            tempTrip = pq.remove();
            currentAirport = tempTrip.getDestinationAirport().getAirportCode();
          // System.out.println("wohooh");
            visited.add(currentAirport);

            //distanceMap.put(currentAirport, tempFlight.getTime());
            //System.out.println(tempTrip);
            //System.out.println(currentAirport);
            //System.out.println(neighbourMap.get(currentAirport.getAirportCode()));
            for (Flight f : neighbourMap.get(currentAirport)) {
                if (!visited.contains(f.getDestinationAirport().getAirportCode()) &&
                        f.getDepartureTime().getTime() >= tempTrip.getArrivalTime()) {
                    Trip t = new Trip(tempTrip.getFlights());
                    t.addFlight(f);
                    pq.add(t);
                }
            }
            //System.out.println("end");
        }

        //tripList.add(tempTrip);
        
        if(visited.contains(destinationAirport.getAirportCode()))
            tripList.add(tempTrip);
        else
            System.out.println("impossible to get there");
 







    }
}
